//
//  YTCacheService.m
//  yangtao
//
//  Created by Tommy on 14/10/17.
//  Copyright (c) 2014年 com.taobao. All rights reserved.
//

#import "KLCacheService.h"
#import "ReactiveCocoa.h"
#import "KLError.h"

@interface KLCacheService()
@property(nonatomic,strong)NSMutableDictionary *caches;

@end

@implementation KLCacheService
KLDEF_SINGLETON(KLCacheService);

- (instancetype)init{
    if(self = [super init]){
        _caches = [[NSMutableDictionary alloc]init];
    }
    return self;
}
- (RACSignal*)allCahces{
    return [RACSignal return:[_caches allValues]];
}
- (RACSignal*)cache:(id<KLICache>)cache forKey:(NSString*)key{
    NSParameterAssert(cache);
    NSParameterAssert(key);
    return [RACSignal return:[_caches objectForKey:key]];
}
- (RACSignal*)setCache:(id<KLICache>)cache forKey:(NSString*)key{
    NSParameterAssert(cache);
    NSParameterAssert(key);
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        _caches[key] = cache;
        [subscriber sendNext:@(YES)];
        [subscriber sendCompleted];
        return nil;
    }];
}
- (RACSignal*)removeCacheForKey:(NSString*)key{
    NSParameterAssert(key);
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        [_caches removeObjectForKey:key];
        [subscriber sendNext:@(YES)];
        [subscriber sendCompleted];
        return nil;
    }];
}

- (RACSignal*)clearAll{
    @weakify(self);
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        @strongify(self);
        @try {
            NSArray *allSignals = [[[self.caches rac_sequence]map:^id(RACTuple *value) {
                id<KLICache> cache = value[1];
                return [cache clearAll];
            }] array];
            
            [[[RACSignal combineLatest:allSignals]and] subscribe:subscriber];
        }
        @catch (NSException *exception) {
            KLSendSimpleError(KLExceptionErrorDomain, KLExceptionErrorCodeException, [exception description]);
            return nil;
        }
        return nil;
    }];
}
- (RACSignal*)clearExpired:(NSDate*)date{
    @weakify(self);
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        @strongify(self);
        @try {
            NSArray *allSignals = [[[self.caches rac_sequence]map:^id(RACTuple *value) {
                id<KLICache> cache = value[1];
                return [cache clearExpired:date];
            }] array];
            
            [[[RACSignal combineLatest:allSignals]and] subscribe:subscriber];
        }
        @catch (NSException *exception) {
            KLSendSimpleError(KLExceptionErrorDomain, KLExceptionErrorCodeException, [exception description]);
            return nil;
        }
        return nil;
    }];
}
- (RACSignal*)objectForKey:(NSString*)key{
    @weakify(self);
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        @strongify(self);
        @try {
            NSArray *allSignals = [[[self.caches rac_sequence]map:^id(RACTuple *value) {
                id<KLICache> cache = value[1];
                return [cache objectForKey:key];
            }] array];
        
            [[[RACSignal concat:allSignals] ignore:nil] subscribe:subscriber];
        }
        @catch (NSException *exception) {
            KLSendSimpleError(KLExceptionErrorDomain, KLExceptionErrorCodeException, [exception description]);
            return nil;
        }
        return nil;
    }];
}
- (RACSignal*)setObject:(id <NSCoding>)object forKey:(NSString *)key{
    @weakify(self);
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        @strongify(self);
        @try {
            NSArray *allSignals = [[[self.caches rac_sequence]map:^id(RACTuple *value) {
                id<KLICache> cache = value[1];
                return [cache setObject:object forKey:key];
            }] array];
            
            [[[RACSignal combineLatest:allSignals] and] subscribe:subscriber];
        }
        @catch (NSException *exception) {
            KLSendSimpleError(KLExceptionErrorDomain, KLExceptionErrorCodeException, [exception description]);
            return nil;
        }
        return nil;
    }];
}
- (RACSignal*)removeObjectForKey:(NSString*)key{
    @weakify(self);
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        @strongify(self);
        @try {
            NSArray *allSignals = [[[self.caches rac_sequence]map:^id(RACTuple *value) {
                id<KLICache> cache = value[1];
                return [cache removeObjectForKey:key];
            }] array];
            
            [[[RACSignal combineLatest:allSignals]and] subscribe:subscriber];
        }
        @catch (NSException *exception) {
            KLSendSimpleError(KLExceptionErrorDomain, KLExceptionErrorCodeException, [exception description]);
            return nil;
        }
        return nil;
    }];
}


+ (RACSignal*)objectForKey:(NSString*)key{
    return [[KLCacheService sharedInstance]objectForKey:key];
}
+ (RACSignal*)setObject:(id<NSCoding>)data forKey:(NSString*)key{
    return [[KLCacheService sharedInstance]setObject:data forKey:key];
}

+ (RACSignal*)removeObjectForKey:(NSString*)key{
    return [[KLCacheService sharedInstance] removeObjectForKey:key];
}

+ (RACSignal*)clearAll{
    return [[KLCacheService sharedInstance]clearAll];

}
+ (RACSignal*)clearExpired:(NSDate*)date{
    return [[KLCacheService sharedInstance] clearExpired:date];
}


@end
